home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-06-24 | 33.9 KB | 1,020 lines | [TEXT/MPS ] |
- /* Definitions of target machine for GNU compiler. For Macintosh MPW.
- Copyright (C) 1987, 1988 Free Software Foundation, Inc.
- Copyright (C) 1989, 1990, 1992 Apple Computer, Inc.
-
- This file is part of GNU CC.
-
- GNU CC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Make sure we don't incorporate any of the bloated Sun FPA stuff. */
-
- #undef SUPPORT_SUN_FPA
-
- /* In general, syntax follows Mororola, */
-
- #define MOTOROLA
-
- /* ... but with some peculiarities. */
-
- #define MPW_ASM
-
- #define ONLY_INT_FIELDS
-
- #define DEFAULT_SHORT_ENUMS 0
-
- /* Include the base 68k definition file, since many tm.h bits are
- identical across versions of the 68k architecture. */
-
- #include "m68k.h"
-
- #define SANE_FLOAT_FORMAT 3
- #define TARGET_FLOAT_FORMAT SANE_FLOAT_FORMAT
- #define HOST_FLOAT_FORMAT SANE_FLOAT_FORMAT
-
- /* Get rid of that bothersome DATA directive before jump tables */
-
- #define JUMP_TABLES_IN_TEXT_SECTION
-
- #define CPP_SPEC "%{m68881:-Dmc68881}%{m68020:-Dmc68020}"
-
- #define CC1_SPEC "%{s*}"
-
- /* Names to predefine in the preprocessor for this target machine. */
- /* Note that this is exactly MPW's set, plus something to distinguish */
- /* from "regular" MPW. */
-
- #define CPP_PREDEFINES \
- "-DMC68000 -Dmc68000 -Dm68k -Dmacintosh -Dapplec -Dmpwgcc"
-
- /* This is true when code gen can treat symbol/label refs as constants. */
-
- #define SYMBOLS_ARE_CONSTANTS 0
-
- /* Define this when code labels and data labels need to be treated
- differently in some way. */
-
- #define MARK_LABEL_SECTION
-
- /* So *library call generation* uses memcpy instead of bcopy, etc. */
-
- #define TARGET_MEM_FUNCTIONS
-
- /* Print subsidiary information on the compiler version in use. */
- #undef TARGET_VERSION
- #define TARGET_VERSION fprintf (stderr, " (680x0, MPW Asm syntax)");
-
- /* Declare Mac-specific globals used in the compiler. */
- extern char *segment_name;
- extern int long_double_type_size;
- extern int current_static_decl;
- extern int current_function_is_pascal;
-
- /* Should override defn in c-decl.c */
-
- #define LONG_DOUBLE_TYPE_SIZE (long_double_type_size)
-
- /* See m68k.h. Default to plain 68000 + SANE + Macsbug symbols. */
-
- #define TARGET_DEFAULT 062000
-
- /* Mac-specific macros used in the machine description to test the flags. */
- /* These are addons to the basic 68K set already defined. */
-
- /* Include MacsBuggable symbols. */
- #define TARGET_MACSBUG (target_flags & 02000)
- /* Compile transcendental fns directly to 881 stuff. */
- #define TARGET_ELEMS881 (target_flags & 04000)
- /* Produce 32-bit references to global data. */
- #define TARGET_32BITDATA (target_flags & 010000)
- /* Generate code for SANE calls directly. */
- #define TARGET_SANE (target_flags & 020000)
- /* Generate code for integer library calls directly. */
- #define TARGET_INTLIB (target_flags & 040000)
- /* Generate pc-relative refs for strings after fn name. */
- #define TARGET_BSTR (target_flags & 0100000)
- /* Generate obscure addressing modifications. */
- #define TARGET_FX30 (target_flags & 0200000)
- /* Suppress all segment directives in the output. */
- #define TARGET_NOSEG (target_flags & 0400000)
-
- #define TARGET_BFUN (target_flags & 01000000)
-
- /* Macro to define tables used to set the flags.
- This is a list in braces of pairs in braces,
- each pair being { "NAME", VALUE }
- where VALUE is the bits to set or minus the bits to clear.
- An empty string NAME is used to identify the default VALUE. */
-
- /* The first part of this list (flags up to 01000 - note octalness) should be identical
- to the generic 68k target. */
-
- #undef TARGET_SWITCHES
- #define TARGET_SWITCHES \
- { { "68020", 5}, \
- { "c68020", 5}, \
- { "68881", 2}, \
- { "bitfield", 4}, \
- { "68000", -5}, \
- { "c68000", -5}, \
- { "soft-float", -0102}, \
- { "nobitfield", -4}, \
- { "rtd", 8}, \
- { "nortd", -8}, \
- { "short", 040}, \
- { "noshort", -040}, \
- { "fpa", 0100}, \
- { "nofpa", -0100}, \
- { "sky", 0200}, \
- { "nosky", -0200}, \
- { "68020-40", 0407}, \
- { "68030", -01400}, \
- { "68030", 7}, \
- { "68040", 01007}, \
- { "bgfull", 02000 }, \
- { "bgoff", -02000 }, \
- { "elems881", 04000}, \
- { "m", 010000}, \
- { "sane", 020000 }, \
- { "insane", -020000 }, \
- { "nointlib", -040000 }, \
- { "bstr", 0100000 }, \
- { "fx30", 0200000 }, \
- { "noseg", 0400000 }, \
- { "bfun", 01000000 }, \
- { "", TARGET_DEFAULT}}
-
- /* In the MPW world, "long double" size depends on compiler flag (yech). */
- /* -elems881 implies -mc68881. */
- /* MPW Asm seems to require -mc68020 when doing large memory model (-m). */
- /* One or the other of sane/mc68881 must be on, but not both. */
-
- #undef OVERRIDE_OPTIONS
- #define OVERRIDE_OPTIONS \
- { \
- if (TARGET_ELEMS881) target_flags |= 2; \
- long_double_type_size = (TARGET_68881 ? 96 : 80); \
- mode_size[(int) XFmode] = (TARGET_68881 ? 12 : 10); \
- mode_unit_size[(int) XFmode] = (TARGET_68881 ? 12 : 10); \
- if (TARGET_68881) target_flags &= ~020000; \
- if (TARGET_SANE) target_flags &= ~2; \
- if (TARGET_32BITDATA) target_flags |= 5; \
- }
-
- /* (what *is* this?) */
- /* Define the largest mode that can be treated as a regular integer. */
-
- /* MPW C tends to think of larger things as block mode objects, so we
- should do this to maintain cross-callability. */
- #define MAX_FIXED_MODE_SIZE (GET_MODE_BITSIZE (SImode))
-
- /* (should probably be scotched for MPW) */
- /* This defines the register which is used to hold the offset table for PIC. */
- /* #define PIC_OFFSET_TABLE_REGNUM 13 */
-
- /* 1 for registers that have pervasive standard uses
- and are not available for the register allocator.
- On the 68000, only the stack pointer is such, but A5 is special to Macs. */
- #undef FIXED_REGISTERS
- #define FIXED_REGISTERS \
- {0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 0, 1, 1, 1, \
- 0, 0, 0, 0, 0, 0, 0, 0, }
-
- /* 1 for registers not available across function calls.
- These must include the FIXED_REGISTERS and also any
- registers that can be used without being saved.
- The latter must include the registers where values are returned
- and the register where structure-value addresses are passed.
- Aside from that, you can include as many other registers as you like. */
- /* This includes all of MPW's scratch registers. */
- #undef CALL_USED_REGISTERS
- #define CALL_USED_REGISTERS \
- {1, 1, 1, 0, 0, 0, 0, 0, \
- 1, 1, 0, 0, 0, 1, 1, 1, \
- 1, 1, 1, 1, 0, 0, 0, 0, }
-
- /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
- On the 68000, the cpu registers can hold any mode but the 68881 registers
- can hold only float modes. And the 68881 registers can't hold anything
- if 68881 use is disabled. Actually, we have to exclude d6 and/or d7 if
- we're using 2 or 3 registers to hold a value, since the "next" register(s)
- would be a0/a1, and things would get really confusing. */
- #undef HARD_REGNO_MODE_OK
- #define HARD_REGNO_MODE_OK(REGNO, MODE) \
- (((REGNO) < 16 && \
- ! (GET_MODE_SIZE (MODE) > 4 && (REGNO) >= 6) && \
- ! (GET_MODE_SIZE (MODE) > 8 && (REGNO) >= 6)) \
- || (TARGET_68881 && GET_MODE_CLASS (MODE) == MODE_FLOAT))
-
- #if 0 /* (not sure if standard version legit tho) */
- /* Value is 1 if it is a good idea to tie two pseudo registers
- when one has mode MODE1 and one has mode MODE2.
- If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
- for any hard reg, then this must be 0 for correct output.
-
- Going by the above defn, we can tie modes for general regs (what about
- d6/d7 tho?) and equal modes for float regs. */
- #define MODES_TIEABLE_P(MODE1, MODE2) \
- (TARGET_68881 ? \
- ((GET_MODE_CLASS (MODE1) == MODE_FLOAT) \
- == (GET_MODE_CLASS (MODE2) == MODE_FLOAT)) : \
- ((GET_MODE_SIZE (MODE1) < 8) && (GET_MODE_SIZE (MODE2) < 8)))
- #endif
-
- /* Disables the assumption that symbols are constants. */
-
- #define CONSTANT_P(X) \
- (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE \
- || GET_CODE (X) == CONST || GET_CODE (X) == HIGH)
-
- #undef CONSTANT_ADDRESS_P
- #define CONSTANT_ADDRESS_P(X) \
- (CONSTANT_P (X) && (GET_CODE (X) != SYMBOL_REF))
-
- /* Register in which address to store a structure value
- arrives in the function.
-
- The MPW 3.0 calling convention is to have things on the stack top. */
- #define STRUCT_VALUE_INCOMING \
- 0
- /*gen_rtx (MEM, Pmode, gen_rtx (PLUS, Pmode, frame_pointer_rtx, \
- gen_rtx (CONST_INT, VOIDmode, 8)))*/
-
- /* Place in which caller passes the structure value address.
- Actually, all that matters about this value is it its rtx_code:
- MEM means push the value on the stack like an argument. */
- #define STRUCT_VALUE \
- 0
- /*gen_rtx (MEM, Pmode, gen_rtx (PRE_DEC, Pmode, stack_pointer_rtx))*/
-
- /* To be MPW-compatible, multi-word structures cannot live in regs. */
-
- #if 0
- #define RETURN_IN_MEMORY(TYPE) \
- ((TREE_CODE (TYPE) == RECORD_TYPE || TREE_CODE (TYPE) == UNION_TYPE) && \
- (GET_MODE_SIZE (TYPE_MODE (TYPE)) > UNITS_PER_WORD))
-
- /* Pad shorts and chars upwards, but nobody else. */
-
- #define FUNCTION_ARG_PADDING(MODE,SIZE) \
- (((MODE) == BLKmode \
- ? (GET_CODE (SIZE) == CONST_INT \
- && INTVAL (SIZE) < PARM_BOUNDARY / BITS_PER_UNIT) \
- : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \
- ? upward : none)
- #endif
-
- #define MAXPARAMS 5
-
- struct call_convention {
- int pascalp;
- int return_regno;
- int parameter_regno[MAXPARAMS];
- /* can flush these eventually */
- struct parameter *last;
- char name[1];
- };
-
- #define SPECIAL_CALLING_CONVENTIONS struct call_convention
-
- #define TYPE_CALL_CONVENTION_PASCAL(T) (TYPE_CALL_CONVENTION (T)->pascalp)
-
- #define INIT_SPECIAL_CALLING_CONVENTIONS(T) \
- (TYPE_CALL_CONVENTION (T) = \
- (struct call_convention *) xmalloc (sizeof(struct call_convention)), \
- TYPE_CALL_CONVENTION (T)->pascalp = 0, \
- TYPE_CALL_CONVENTION (T)->return_regno = -1, \
- TYPE_CALL_CONVENTION (T)->parameter_regno[0] = -1, \
- TYPE_CALL_CONVENTION (T)->parameter_regno[1] = -1, \
- TYPE_CALL_CONVENTION (T)->parameter_regno[2] = -1, \
- TYPE_CALL_CONVENTION (T)->parameter_regno[3] = -1, \
- TYPE_CALL_CONVENTION (T)->parameter_regno[4] = -1)
-
- #define COMPARE_CALL_CONVENTION(CC1,CC2) \
- (((CC1) == 0 && (CC2) == 0) \
- || ((CC1) != 0 && (CC2) != 0 \
- && (CC1)->pascalp == (CC2)->pascalp \
- && (CC1)->return_regno == (CC2)->return_regno \
- && (CC1)->parameter_regno[0] == (CC2)->parameter_regno[0] \
- && (CC1)->parameter_regno[1] == (CC2)->parameter_regno[1] \
- && (CC1)->parameter_regno[2] == (CC2)->parameter_regno[2] \
- && (CC1)->parameter_regno[3] == (CC2)->parameter_regno[3] \
- && (CC1)->parameter_regno[4] == (CC2)->parameter_regno[4]))
-
- #define COPY_CALL_CONVENTION(CC1,CC2) \
- { if ((CC1) != NULL && (CC2) != NULL) \
- { \
- /* (CC1)->pascalp = (CC2)->pascalp; should do? */ \
- (CC1)->return_regno = (CC2)->return_regno; \
- (CC1)->parameter_regno[0] = (CC2)->parameter_regno[0]; \
- (CC1)->parameter_regno[1] = (CC2)->parameter_regno[1]; \
- (CC1)->parameter_regno[2] = (CC2)->parameter_regno[2]; \
- (CC1)->parameter_regno[3] = (CC2)->parameter_regno[3]; \
- (CC1)->parameter_regno[4] = (CC2)->parameter_regno[4]; } }
-
- #define PRINT_CALL_CONVENTION(FILE,NODE,INDENT) \
- { struct call_convention *cc = TYPE_CALL_CONVENTION (NODE); \
- int i; \
- extern char *reg_names[]; \
- if (cc->pascalp) fprintf(FILE, " pascal"); \
- if (cc->return_regno >= 0) \
- fprintf (FILE, " return %s", reg_names[cc->return_regno]); \
- fprintf (FILE, " args"); \
- for (i = 0; i < MAXPARAMS; ++i) { \
- if (cc->parameter_regno[i] >= 0) \
- fprintf (FILE, " %s", reg_names[cc->parameter_regno[i]]); \
- } \
- }
-
- /* Always false on the Mac, even for pascal fns (really?). */
-
- #undef RETURN_POPS_ARGS
- #define RETURN_POPS_ARGS(FUNTYPE,SIZE) 0
-
- /* On the Mac the return value is in D0 except for pascal routines, but
- pascal fakes this, since space has to be reserved ahead of time, which
- needs mods in the code proper. */
- /* 68881 functions return floats in FP0. */
-
- #undef FUNCTION_VALUE
- #define FUNCTION_VALUE(VALTYPE, FUNC) ((rtx) function_value (VALTYPE, FUNC))
-
- #if 0 /* old */
- #define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx (REG, TYPE_MODE (VALTYPE), \
- (TARGET_68881 && \
- (GET_MODE_CLASS (TYPE_MODE (VALTYPE)) == MODE_FLOAT) ? \
- 16 : 0))
- #endif
-
- /* The actual offset gets filled after assign_parms is run... */
-
- #define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) \
- ((rtx) function_outgoing_value (VALTYPE, FUNC))
-
- #if 0
- #define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) \
- (((FUNC) && current_function_is_pascal) ? \
- gen_rtx (MEM, TYPE_MODE (VALTYPE), \
- gen_rtx (PLUS, Pmode, \
- frame_pointer_rtx, \
- gen_rtx (CONST_INT, VOIDmode, 12345))) : \
- FUNCTION_VALUE (VALTYPE, FUNC))
- #endif
-
- /* Define how to find the value returned by a library function
- assuming the value has mode MODE. */
-
- /* 1 if N is a possible register number for a function value.*/
- /* This is d0 or fp0. */
-
- #undef FUNCTION_VALUE_REGNO_P
- #define FUNCTION_VALUE_REGNO_P(N) \
- ((N) == 0 || (TARGET_68881 && (N) == 16))
-
- /* MPW doesn't know diddly-squat about PCC. */
-
- #undef PCC_STATIC_STRUCT_RETURN
-
- #undef FUNCTION_ARG
- #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- ((rtx) function_arg (&CUM, MODE, NAMED))
-
- #undef FUNCTION_ARG_PARTIAL_NREGS
- #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
- ((0 /* TARGET_REGPARM */ && (CUM.size) < 8 \
- && 8 < ((CUM.size) + ((MODE) == BLKmode \
- ? int_size_in_bytes (TYPE) \
- : GET_MODE_SIZE (MODE)))) \
- ? 2 - (CUM.size) / 4 : 0)
-
- #if 0
- #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- (/* (TARGET_REGPARM && (CUM) < 8) ? gen_rtx (REG, (MODE), (CUM) / 4) : */ 0)
- #undef FUNCTION_ARG_PARTIAL_NREGS
- #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
- ((0 /* TARGET_REGPARM */ && (CUM) < 8 \
- && 8 < ((CUM) + ((MODE) == BLKmode \
- ? int_size_in_bytes (TYPE) \
- : GET_MODE_SIZE (MODE)))) \
- ? 2 - (CUM) / 4 : 0)
- #endif
-
- /* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
-
- #undef FUNCTION_PROFILER
- #define FUNCTION_PROFILER(FILE, LABELNO) \
- fprintf (FILE, "\tlea LP%d,a0\n\tjsr fn##count\n", LABELNO)
-
- /* Output assembler code to FILE to initialize this source file's
- basic block profiling info, if that has not already been done. */
-
- #undef FUNCTION_BLOCK_PROFILER
- #define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \
- fprintf (FILE, "\ttst.l LPBX0\n\tbne LPI%d\n", LABELNO); \
- fprintf (FILE, "\tpea LPBX0\n\tjsr bb##init\n\taddq.l #4,sp\n"); \
- fprintf (FILE, "LPI%d:\n", LABELNO);
-
- /* Output assembler code to FILE to increment the entry-count for
- the BLOCKNO'th basic block in this source file. */
-
- #undef BLOCK_PROFILER
- #define BLOCK_PROFILER(FILE, BLOCKNO) \
- fprintf (FILE, "\taddq.l #1,LPBX2+%d\n", 4 * BLOCKNO)
-
- /* If the memory address ADDR is relative to the frame pointer,
- correct it to be relative to the stack pointer instead.
- This is for when we don't use a frame pointer.
- ADDR should be a variable name. */
-
- #define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
- { int offset = -1; \
- rtx regs = stack_pointer_rtx; \
- if (ADDR == frame_pointer_rtx) \
- offset = 0; \
- else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx \
- && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
- offset = INTVAL (XEXP (ADDR, 1)); \
- else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx) \
- { rtx other_reg = XEXP (ADDR, 1); \
- offset = 0; \
- regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
- else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx) \
- { rtx other_reg = XEXP (ADDR, 0); \
- offset = 0; \
- regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
- else if (GET_CODE (ADDR) == PLUS \
- && GET_CODE (XEXP (ADDR, 0)) == PLUS \
- && XEXP (XEXP (ADDR, 0), 0) == frame_pointer_rtx \
- && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
- { rtx other_reg = XEXP (XEXP (ADDR, 0), 1); \
- offset = INTVAL (XEXP (ADDR, 1)); \
- regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
- else if (GET_CODE (ADDR) == PLUS \
- && GET_CODE (XEXP (ADDR, 0)) == PLUS \
- && XEXP (XEXP (ADDR, 0), 1) == frame_pointer_rtx \
- && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
- { rtx other_reg = XEXP (XEXP (ADDR, 0), 0); \
- offset = INTVAL (XEXP (ADDR, 1)); \
- regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
- if (offset >= 0) \
- { int regno; \
- extern char call_used_regs[]; \
- for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- offset += 12; \
- for (regno = 0; regno < 16; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- offset += 4; \
- offset -= 4; \
- ADDR = plus_constant (regs, offset + (DEPTH)); } } \
-
- /* Disable function cse even though it's good, because this screws up
- direct functions and I'm too lazy to put in the exact test everywhere. */
-
- #define NO_FUNCTION_CSE
-
- /* (this probably needs work) */
-
- /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
- that is a valid memory address for an instruction.
- The MODE argument is the machine mode for the MEM expression
- that wants to use this address.
-
- The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */
-
- /* See m68k.h, I am a little paranoid about MPW_C's macro expansion*/
-
- #define ASM_IDENTIFY_GCC(FILE) \
- { extern char *version_string; \
- fprintf((FILE), "; Compiled by MPW GCC %s\n", version_string); }
-
- /* Dump out all sorts of random header stuff that MPW wants. */
-
- #undef ASM_FILE_START
- #define ASM_FILE_START(FILE) \
- { \
- init_import_for_file(); \
- ASM_SEGMENT_NAME(FILE, segment_name); \
- if (TARGET_68040) \
- fprintf (FILE, "\tMACHINE MC68040\n"); \
- else if (TARGET_68020) \
- fprintf (FILE, "\tMACHINE MC68020\n"); \
- else \
- fprintf (FILE, "\tMACHINE MC68000\n"); \
- if (TARGET_68881) \
- fprintf (FILE, "\tMC68881\n"); \
- if (TARGET_32BITDATA && TARGET_68020) \
- fprintf (FILE, "\tFORWARD LONG\n"); \
- fprintf (FILE, "\tSTRING ASIS\n"); \
- fprintf (FILE, "\tCASE ON\n"); \
- }
-
- /* Output to assembler file text saying following lines
- may contain character constants, extra white space, comments, etc. */
-
- #undef ASM_APP_ON
- #define ASM_APP_ON "; begin asm code\n"
-
- /* Output to assembler file text saying following lines
- no longer contain unusual constructs. */
-
- #undef ASM_APP_OFF
- #define ASM_APP_OFF "; end asm code\n"
-
- #define IMPORT_DECL(decl) import_decl (decl);
-
- #define ENCODE_SECTION_INFO(decl) /*fprintf(stderr, "ENCODE:\n"); debug_tree (decl);*/
-
- /* Defining this suppresses attempts to generate calls to `__main'. */
-
- #define INIT_SECTION_ASM_OP
-
- /* Output before read-only data. */
-
- #undef TEXT_SECTION_ASM_OP
- #define TEXT_SECTION_ASM_OP "\tCODE"
-
- /* Output before writable data. */
-
- #undef DATA_SECTION_ASM_OP
- #define DATA_SECTION_ASM_OP "\tDATA"
- #undef READONLY_DATA_SECTION
- #define READONLY_DATA_SECTION data_section
-
- /* Force all data thingies and variables to be data, except for strings
- glued onto the end of function modules. */
-
- #undef SELECT_SECTION
- #define SELECT_SECTION(exp, reloc)
-
- /* The MPW proc declaration autoswitches to text section, so we need this
- to tell GCC that this has happened. */
-
- #define EXTRA_SECTION_FUNCTIONS \
- void force_text_section () { in_section = in_text; }
-
- /* Note that PROC in MPW asm automatically declares CODE, so we
- have to change the assumed section without writing the directive. */
-
- #define ASM_PREDECLARE_FUNCTION_NAME(FILE,NAME,DECL) \
- { \
- assemble_name (FILE, NAME); \
- fprintf (FILE, "%% \tPROC\n"); \
- force_text_section (); \
- import_undefined (FILE); \
- FreeImps(); \
- text_section(); \
- }
-
- #define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \
- { \
- if (TARGET_FX30) \
- fprintf (FILE, "\tIMPORT _StaticDataArea\n"); \
- if ((DECL) && TREE_PUBLIC (DECL)) \
- fprintf (FILE, "\tEXPORT "); \
- else \
- fprintf (FILE, "\tENTRY "); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, "\n"); \
- ASM_OUTPUT_LABEL (FILE, NAME); \
- }
-
- #define ASM_DECLARE_OBJECT_NAME(asm_out_file, name, decl)
-
- #define ASM_DECLARE_VARIABLE_NAME(FILE,NAME,PUBLIC) \
- { \
- assemble_name (FILE, NAME); \
- fprintf (FILE, " \tRECORD"); \
- if (PUBLIC) \
- fprintf (FILE, "\tEXPORT\n"); \
- else \
- fprintf (FILE, "\tENTRY\n"); \
- import_undefined (FILE); \
- }
-
- #define ASM_DECLARE_CONSTANT_NAME(FILE,NUM,EXP) \
- { char label[256];\
- ASM_GENERATE_INTERNAL_LABEL (label, "LC", NUM); \
- if (! (TARGET_BSTR && TREE_CODE(EXP) == STRING_CST && current_function_decl && ! assembling_static_variable)) \
- { \
- assemble_name (FILE, label); \
- fprintf (FILE, "\tRECORD\n"); \
- } \
- }
-
- #define OUTPUT_LABELED_CONSTANT(asm_out_file,const_labelno,exp) \
- if (! (TARGET_BSTR && TREE_CODE (exp) == STRING_CST && current_function_decl && ! assembling_static_variable)) \
- { \
- output_constant (exp, \
- (TREE_CODE (exp) == STRING_CST \
- ? TREE_STRING_LENGTH (exp) \
- : int_size_in_bytes (TREE_TYPE (exp)))); \
- }
-
- #define REMEMBER_CONSTANT_LABEL(lbl,exp) \
- if (TARGET_BSTR && TREE_CODE (exp) == STRING_CST && current_function_decl && ! assembling_static_variable) \
- record_a_string (lbl, TREE_STRING_POINTER (exp));
-
- /* Exportation is done by general declaration macros. */
-
- #undef GLOBAL_ASM_OP
- /*#define GLOBALS_ASM_OP ????*/
-
- #undef ASM_GLOBALIZE_LABEL
- #define ASM_GLOBALIZE_LABEL(FILE,NAME) /* */
-
- #define ASM_OUTPUT_EXTERNAL(FILE,DECL,NAME) ;
-
- #if 0
- /* do this eventually */
- #define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, RTL) \
- do { fputs ("\t.IMPORT ", FILE); \
- assemble_name (FILE, XSTR ((RTL), 0)); \
- fputs (",CODE\n", FILE); \
- } while (0)
- #endif
-
- /* This is how to output the definition of a user-level label named NAME,
- such as the label on a static function or variable NAME. */
-
- #undef ASM_OUTPUT_LABEL
- #define ASM_OUTPUT_LABEL(FILE,NAME) \
- { assemble_name (FILE, NAME); fputs (":\n", FILE); }
-
- /* This is how to output a reference to a user-level label named NAME.
- `assemble_name' uses this. */
-
- /* User-level labels (almost) always have one extra character that should
- be ignored. They may also conflict with MPW Asm register names. */
-
- #undef ASM_OUTPUT_LABELREF
- #define ASM_OUTPUT_LABELREF(FILE,NAME) \
- { \
- extern char *avoid_mpw_register_name(); \
- char *tname = avoid_mpw_register_name (NAME); \
- fprintf (FILE, "%s", tname); \
- }
-
- /* This is how to output an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-
- #undef ASM_OUTPUT_INTERNAL_LABEL
- #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
- fprintf (FILE, "%s#%d:\n", PREFIX, NUM)
-
- /* This is how to store into the string LABEL
- the symbol_ref name of an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class.
- This is suitable for output with `assemble_name'. */
-
- #undef ASM_GENERATE_INTERNAL_LABEL
- #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "%s#%d", PREFIX, NUM)
-
- /* This is how to output an assembler line defining a `float' constant. */
-
- #undef ASM_OUTPUT_FLOAT
- #define ASM_OUTPUT_FLOAT(FILE,VALUE) \
- fprintf (FILE, "\tDC.S \"%.9g\"\n", (VALUE))
-
- #undef ASM_OUTPUT_DOUBLE
- #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
- fprintf (FILE, "\tDC.D \"%.20g\"\n", (VALUE))
-
- #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
- output_mpw_long_double (FILE, VALUE)
-
- /* This is how to output an assembler line defining an `int' constant. */
-
- #undef ASM_OUTPUT_INT
- #define ASM_OUTPUT_INT(FILE,VALUE) \
- (fprintf (FILE, "\tDC.L "), \
- output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
-
- /* Likewise for `char' and `short' constants. */
-
- #undef ASM_OUTPUT_SHORT
- #define ASM_OUTPUT_SHORT(FILE,VALUE) \
- (fprintf (FILE, "\tDC.W "), \
- output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
-
- #undef ASM_OUTPUT_CHAR
- #define ASM_OUTPUT_CHAR(FILE,VALUE) \
- (fprintf (FILE, "\tDC.B "), \
- output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
-
- /* This is how to output an assembler line for a numeric constant byte. */
-
- #undef ASM_OUTPUT_BYTE
- #define ASM_OUTPUT_BYTE(FILE,VALUE) \
- fprintf (FILE, "\tDC.B $%x\n", (VALUE))
-
- /* This is how to output an insn to push a register on the stack.
- It need not be very fast code. */
-
- #undef ASM_OUTPUT_REG_PUSH
- #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
- fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[REGNO])
-
- /* This is how to output an insn to pop a register from the stack.
- It need not be very fast code. */
-
- #undef ASM_OUTPUT_REG_POP
- #define ASM_OUTPUT_REG_POP(FILE,REGNO) \
- fprintf (FILE, "\tmove.l (sp)+,%s\n", reg_names[REGNO])
-
- /* This is how to output an element of a case-vector that is absolute.
- (The 68000 does not use such vectors,
- but we must define this macro anyway.) */
-
- #undef ASM_OUTPUT_ADDR_VEC_ELT
- #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
- fprintf (FILE, "\tDC.L L#%d\n", VALUE)
-
- /* This is how to output an element of a case-vector that is relative. */
-
- #undef ASM_OUTPUT_ADDR_DIFF_ELT
- #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
- fprintf (FILE, "\tDC.W L#%d-L#%d\n", VALUE, REL)
-
- /* This is how to output an assembler line
- that says to advance the location counter
- to a multiple of 2**LOG bytes. */
-
- #undef ASM_OUTPUT_ALIGN
- #define ASM_OUTPUT_ALIGN(FILE,LOG) \
- if ((LOG) == 1) \
- fprintf (FILE, "\tALIGN 2\n"); \
- else if ((LOG) != 0) \
- abort ();
-
- /* A "skip" in MPW is better done by filling with zeros. */
-
- #undef ASM_OUTPUT_SKIP
- #define ASM_OUTPUT_SKIP(FILE,SIZE) \
- fprintf (FILE, "\tDCB.B %d,0\n", (SIZE))
-
- /* This says how to output an assembler line
- to define a global common symbol. */
-
- #undef ASM_OUTPUT_COMMON
- #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
- do { \
- fprintf (FILE, "\n"); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, " \tRECORD\tEXPORT\n"); \
- fprintf (FILE, "\tDS.B %d\n", ROUNDED); \
- fprintf (FILE, "\tENDR\t; "); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, "\n"); \
- } while (0)
-
- /* This says how to output an assembler line
- to define a local common symbol. */
-
- #undef ASM_OUTPUT_LOCAL
- #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
- do { \
- assemble_name (FILE, NAME); \
- /*fprintf (FILE, " \tRECORD\tENTRY\n");*/ \
- fprintf (FILE, "\tDS.B %d\n", ROUNDED); \
- /*fprintf (FILE, "\tENDR\t; "); */ \
- /* assemble_name (FILE, NAME);*/ \
- fprintf (FILE, "\n"); \
- } while (0)
-
- /* Store in OUTPUT a string (made with alloca) containing
- an assembler-name for a local static variable named NAME.
- LABELNO is an integer which is different for each call. */
-
- #undef ASM_FORMAT_PRIVATE_NAME
- #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
- ((OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \
- sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO)))
-
- /* MPW reverses the characters meaning newline and cr. */
-
- #undef TARGET_NEWLINE
- #define TARGET_NEWLINE 13
- #undef TARGET_CR
- #define TARGET_CR 10
-
- /* MPW strings need a dedicated routine to write them out properly. */
-
- #define ASM_OUTPUT_ASCII(FILE,STRING,SIZE) \
- output_mpw_string (FILE, STRING, SIZE);
-
- /* At the end of a function module, prepare for the next module. */
-
- #define ASM_FUNCTION_END(FILE) \
- { extern char *current_function_name; \
- fprintf (FILE, "\tENDP\t; %s\n", current_function_name); \
- }
-
- /* At the end of a variable module, prepare for the next module. */
-
- #define ASM_VARIABLE_END(FILE,NAME) \
- { \
- fprintf (FILE, "\tENDR\t; "); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, "\n"); \
- }
-
- /* At the end of a variable module, prepare for the next module. */
-
- #define ASM_CONSTANT_END(FILE,NUM,EXP) \
- if (! (TARGET_BSTR && TREE_CODE(EXP) == STRING_CST && current_function_decl && ! assembling_static_variable)) \
- fprintf (FILE, "\tENDR\n");
-
- /* Write out a segment name. */
-
- #define ASM_SEGMENT_NAME(FILE,NAME) \
- if (! TARGET_NOSEG) fprintf(FILE, "\tSEG '%s'\n", NAME);
-
- /* Write out an import of a name not in this module. */
-
- #define ASM_IMPORT_NAME(FILE, NAME, DATA_P) \
- { \
- fprintf (FILE, "\tIMPORT "); \
- assemble_name (FILE, NAME); \
- if(DATA_P) \
- fprintf(FILE, ":DATA\n"); \
- else \
- fprintf(FILE, ":CODE\n");\
- }
-
- /* At the end of the whole file, spit out a last directive. */
-
- #define ASM_FILE_END(FILE) \
- fprintf(FILE, "\tEND\n");
-
- /* Magic for the handling of 10/12 byte long doubles. */
-
- #ifdef macintosh
-
- #undef REAL_VALUE_TYPE
- #define REAL_VALUE_TYPE extended
- #define REAL_IS_NOT_DOUBLE
-
- #define REAL_ARITHMETIC(value, code, x, y) mpw_real_arithmetic(&value, code, x, y)
- #define REAL_VALUE_TO_INT(low, high, x) mpw_real_to_int(&low, &high, x)
- #define REAL_VALUE_FROM_UNSIGNED_INT(x, low, high) \
- x = (double) high;\
- x *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))\
- * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)));\
- x += (double) (unsigned HOST_WIDE_INT) low;
- #define REAL_VALUE_FROM_INT(d, low, high) \
- if (high < 0) \
- { \
- d = (double) (~ high); \
- d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) \
- * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))); \
- d += (double) (unsigned HOST_WIDE_INT) (~ low); \
- d = (- d - 1.0); \
- } \
- else \
- { \
- d = (double) high; \
- d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) \
- * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))); \
- d += (double) (unsigned HOST_WIDE_INT) low; \
- }
-
-
- int mpw_real_to_int(int *low, int *high, REAL_VALUE_TYPE x);
- int mpw_real_arithmetic(REAL_VALUE_TYPE *value,
- int code,
- REAL_VALUE_TYPE x,
- REAL_VALUE_TYPE y);
-
- #endif /* macintosh */
-
- /* Don't bother to try to do anything special. Default will be to use
- 'double', which is adequate except for trying to cross-compile extended
- float constants on a machine that doesn't support them, which I don't
- want to bother with right now. Note that cross-compilation of vars,
- arith, etc, is still ok - only constants might be wrong. */
-
-
- /* Machinery to add math-oriented builtin functions. */
-
- #define ADDITIONAL_BUILTINS \
- if (flag_apple && TARGET_ELEMS881) \
- { \
- builtin_function ("cos", extended_ftype_extended, BUILT_IN_COS, 0); \
- builtin_function ("sin", extended_ftype_extended, BUILT_IN_SIN, 0); \
- builtin_function ("tan", extended_ftype_extended, BUILT_IN_TAN, 0); \
- builtin_function ("asin", extended_ftype_extended, BUILT_IN_ASIN, 0); \
- builtin_function ("acos", extended_ftype_extended, BUILT_IN_ACOS, 0); \
- builtin_function ("atan", extended_ftype_extended, BUILT_IN_ATAN, 0); \
- builtin_function ("sinh", extended_ftype_extended, BUILT_IN_SINH, 0); \
- builtin_function ("cosh", extended_ftype_extended, BUILT_IN_COSH, 0); \
- builtin_function ("tanh", extended_ftype_extended, BUILT_IN_TANH, 0); \
- builtin_function ("exp", extended_ftype_extended, BUILT_IN_EXP, 0); \
- builtin_function ("log", extended_ftype_extended, BUILT_IN_LOG, 0); \
- builtin_function ("log10", extended_ftype_extended, BUILT_IN_LOG10, 0); \
- builtin_function ("sqrt", extended_ftype_extended, BUILT_IN_FSQRT, 0); \
- }
-
- #define ADDITIONAL_BUILT_IN_CASES \
- case BUILT_IN_TAN: \
- case BUILT_IN_ASIN: \
- case BUILT_IN_ACOS: \
- case BUILT_IN_ATAN: \
- case BUILT_IN_SINH: \
- case BUILT_IN_COSH: \
- case BUILT_IN_TANH: \
- case BUILT_IN_EXP: \
- case BUILT_IN_LOG: \
- case BUILT_IN_LOG10:
-
- #define ADDITIONAL_BUILT_IN_OPS \
- case BUILT_IN_TAN: \
- builtin_optab = tan_optab; break; \
- case BUILT_IN_ASIN: \
- builtin_optab = asin_optab; break; \
- case BUILT_IN_ACOS: \
- builtin_optab = acos_optab; break; \
- case BUILT_IN_ATAN: \
- builtin_optab = atan_optab; break; \
- case BUILT_IN_SINH: \
- builtin_optab = sinh_optab; break; \
- case BUILT_IN_COSH: \
- builtin_optab = cosh_optab; break; \
- case BUILT_IN_TANH: \
- builtin_optab = tanh_optab; break; \
- case BUILT_IN_EXP: \
- builtin_optab = exp_optab; break; \
- case BUILT_IN_LOG: \
- builtin_optab = log_optab; break; \
- case BUILT_IN_LOG10: \
- builtin_optab = log10_optab; break;
-
- /* Many pragmas to handle. */
-
- /* Code to handle #pragma directives. The interface is a bit messy,
- but there's no simpler way to do this while still using yylex. */
- /* This was taken from m88k.h. */
-
- #define HANDLE_MPW_PRAGMA
-
- #define HANDLE_SEGMENT_PRAGMA
-
- #define APPLE_DEFAULT 1
-
- #define DEFAULT_INCLUDE_ENV "CIncludes"
-
- #undef PARM_BOUNDARY
- #define PARM_BOUNDARY 16
-
- typedef struct cumargs {
- int size;
- int count;
- struct call_convention *p;
- } CumArgs;
-
- #undef CUMULATIVE_ARGS
- #define CUMULATIVE_ARGS CumArgs
-
- #undef FUNCTION_ARG_ADVANCE
- #define FUNCTION_ARG_ADVANCE(CUM,MODE,TYPE,NAMED) \
- ((CUM).size += ((MODE) != BLKmode \
- ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
- : (int_size_in_bytes (TYPE) + 3) & ~3), (CUM).count += 1)
-
- #undef INIT_CUMULATIVE_ARGS
- #define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
- ((CUM).size = 0, \
- (CUM).count = 0, \
- (CUM).p = ((FNTYPE) ? TYPE_CALL_CONVENTION (FNTYPE) : NULL))
-
- /* Declarations of assorted functions called from the machine description. */
-
- char *output_sane_convert();
- char *output_sane_2();
- char *output_sane_3();
- char *output_sane_tst();
- char *output_sane_cmp();
- char *output_move_extended();
- char *output_move_const_long_double();
- char *output_lib_convert();
- char *output_int_lib_call();
-